<template>
  <el-container class="panel-container setting-panel">
    <el-tabs v-model="activeTab" class="setting-panel-tabs">
      <!-- 组件属性设置 -->
      <el-tab-pane name="1">
        <template #label>
          <div class="panel-tabs-header">
            <span class="header-content">{{ i18nt('designer.hint.widgetSetting') }}</span>
          </div>
        </template>
        <el-scrollbar class="setting-scrollbar" :style="{height: '100%'}">
          <div class="container-setting-panel">
            <!-- 字段属性 -->
            <template v-if="!!designer.selectedWidget && !designer.selectedWidget.category">
              <el-form ref="fieldSettingFormRef" :model="optionModel" size="small" label-position="left" label-width="120px" class="setting-form"
                      @submit.prevent>
                <el-collapse v-model="widgetActiveCollapseNames" class="setting-collapse">
                  <el-collapse-item name="1" v-if="showCollapse(commonProps)" :title="i18nt('designer.setting.commonSetting')">
                    <template v-for="(editorName, propName) in commonProps">
                      <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                                :designer="designer" :selected-widget="selectedWidget" :option-model="optionModel"
                      >
                      </component>
                    </template>
                  </el-collapse-item>
                  <el-collapse-item name="2" v-if="showCollapse(advProps)" :title="i18nt('designer.setting.advancedSetting')">
                    <template v-for="(editorName, propName) in advProps">
                      <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                                :designer="designer" :selected-widget="selectedWidget" :option-model="optionModel"></component>
                    </template>
                  </el-collapse-item>
                  <el-collapse-item name="3" v-if="showEventCollapse() && showCollapse(eventProps)" :title="i18nt('designer.setting.eventSetting')">
                    <template v-for="(editorName, propName) in eventProps">
                      <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                                :designer="designer" :selected-widget="selectedWidget" :option-model="optionModel"></component>
                    </template>
                  </el-collapse-item>
                </el-collapse>
              </el-form>
            </template>
            <!-- 容器属性 -->
            <template v-if="(!!designer.selectedWidget && !!designer.selectedWidget.category)">
              <el-form :model="optionModel" size="small" label-position="left" label-width="120px" class="setting-form"
                      @submit.prevent>
                <el-collapse v-model="widgetActiveCollapseNames" class="setting-collapse">
                  <el-collapse-item name="1" v-if="showCollapse(commonProps)" :title="i18nt('designer.setting.commonSetting')">
                    <template v-for="(editorName, propName) in commonProps">
                      <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                                :designer="designer" :selected-widget="selectedWidget" :option-model="optionModel"></component>
                    </template>
                  </el-collapse-item>
  
                  <el-collapse-item name="2" v-if="showCollapse(advProps)" :title="i18nt('designer.setting.advancedSetting')">
                    <template v-for="(editorName, propName) in advProps">
                      <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                                :designer="designer" :selected-widget="selectedWidget" :option-model="optionModel"></component>
                    </template>
                  </el-collapse-item>
  
                  <el-collapse-item name="3" v-if="showEventCollapse() && showCollapse(eventProps)" :title="i18nt('designer.setting.eventSetting')">
                    <template v-for="(editorName, propName) in eventProps">
                      <component v-if="hasPropEditor(propName, editorName)" :is="getPropEditor(propName, editorName)"
                                :designer="designer" :selected-widget="selectedWidget" :option-model="optionModel"></component>
                    </template>
                  </el-collapse-item>
                </el-collapse>
              </el-form>
            </template>
            <template v-if="!designer.selectedWidget">
              <div class="no-widget-hint">请选择一个组件</div>
            </template>
          </div>
        </el-scrollbar>
      </el-tab-pane>

      <!-- 表单属性设置 -->
      <el-tab-pane v-if="!!designer" name="2">
        <template #label>
          <div class="panel-tabs-header">
            <span class="header-content">{{ i18nt('designer.hint.formSetting') }}</span>
          </div>
        </template>
        <el-scrollbar class="setting-scrollbar" :style="{height: '100%'}">
          <form-setting :designer="designer" :form-config="formConfig"></form-setting>
        </el-scrollbar>
      </el-tab-pane>
    </el-tabs>
    <!-- 事件编辑弹窗 -->
    <div v-if="eventDialogStore.visible" >
      <vxe-modal
        :="dialogAttrs"
        :title="i18nt('designer.setting.editWidgetEventHandler')"
        v-model="eventDialogStore.visible"
      >
        <el-alert type="info" :closable="false" :title="eventHeader" class="alert-padding"></el-alert>
        <AceCodeEditor mode="javascript" :readonly="false" v-model="eventHandlerCode" ref="ecEditor"></AceCodeEditor>
        <el-alert type="info" :closable="false" title="}" class="alert-padding"></el-alert>
        <template #footer>
          <div class="dialog-footer">
            <el-button @click="eventDialogStore.visible = false">
              {{i18nt('designer.hint.cancel')}}</el-button>
            <el-button type="primary" @click="saveEventHandler">
              {{i18nt('designer.hint.confirm')}}</el-button>
          </div>
        </template>
      </vxe-modal>
    </div>

  </el-container>
</template>

<script>
import FormSetting from './form-setting'
import { baseAttrs } from '@/components/dialogs/cfg/base-cofig.js'
import { CodeEditor, AceCodeEditor } from '@/components/vf-editor'
import PropertyEditors from './property-editor/index'
import WidgetProperties from './propertyRegister'
import { addWindowResizeHandler } from "@/utils/util"
import i18n from "@/utils/i18n"
import eventBus from "@/utils/event-bus"
import { VfMessage } from '@/utils/vf-utils'
import emitter from "@/utils/emitter"
import { propertyRegistered } from "@/components/form-designer/setting-panel/propertyRegister";

const {COMMON_PROPERTIES, ADVANCED_PROPERTIES, EVENT_PROPERTIES} = WidgetProperties

export default {
  name: "SettingPanel",
  componentName: "SettingPanel",
  mixins: [i18n, emitter],
  components: {
    CodeEditor,
    FormSetting,
    AceCodeEditor,
    ...PropertyEditors,
  },
  props: {
    designer: Object,
    selectedWidget: Object,
    formConfig: Object,
    globalDsv: { type: Object, default: () => ({}) },
  },
  inject: ['getDesignerConfig'],
  data() {
    return {
      designerConfig: this.getDesignerConfig(),

      scrollerHeight: 0,

      activeTab: "2",
      widgetActiveCollapseNames: ['1', '3'], //['1', '2', '3'],
      formActiveCollapseNames: ['1', '2'],

      commonProps: COMMON_PROPERTIES,
      advProps: ADVANCED_PROPERTIES,
      eventProps: EVENT_PROPERTIES,

      eventHandlerCode: '',
      curEventName: '',
      eventHeader: '',

      subFormChildWidgetFlag: false,
      // 弹窗属性配置
      dialogAttrs: {
        ...baseAttrs,
        className: 'vf-designer-dialog vf-setting-dialog'
      },
      // 弹窗数据集
      dialogStore: {
        dragClass: ['.drag-dialog.el-dialog', '.drag-dialog .el-dialog__header'],
      },
      eventDialogStore: {
        visible: false
      }
    }
  },
  computed: {
    optionModel: {
      get() {
        return this.selectedWidget.options
      },

      set(newValue) {
        this.selectedWidget.options = newValue
      }
    },

  },
  watch: {
    'designer.selectedWidget': {
      handler(val) {
        if (!!val) {
          this.activeTab = "1"
        }
        this.clearSettingValidate()
      }
    },
    'selectedWidget.options': {  //组件属性变动后，立即保存表单JSON！！
      deep: true,
      handler() {
        this.designer.saveCurrentHistoryStep()
      }
    },
    formConfig: {
      deep: true,
      handler() {
        this.designer.saveCurrentHistoryStep()
      }
    },

  },
  created() {
    this.on$('editEventHandler', (eventParams) => {
      // debugger
      this.editEventHandler(eventParams[0], eventParams[1])
    })

    this.designer.handleEvent('form-css-updated', (cssClassList) => {
      this.designer.setCssClassList(cssClassList)
    })
  },
  mounted() {
    this.activeTab = !this.designer.selectedWidget ? "2" : "1"
    this.scrollerHeight = window.innerHeight - 56 + 'px'
    // addWindowResizeHandler(() => {
    //   this.$nextTick(() => {
    //     this.scrollerHeight = window.innerHeight - 56 + 'px'
    //   })
    // })
  },
  methods: {
    showEventCollapse() {
      if (this.designerConfig['eventCollapse'] === undefined) {
        return true
      }

      return !!this.designerConfig['eventCollapse']
    },

    hasPropEditor(propName, editorName) {
      if (!editorName) {
        return false
      }

      /* alert组件注册了两个type属性编辑器，跳过第一个type属性编辑器，只显示第二个alert-type属性编辑器！！ */
      if (propName.indexOf('-') <= -1) {
        let uniquePropName = this.selectedWidget.type + '-' + propName
        if (propertyRegistered(uniquePropName)) {
          return false
        }
      }

      let originalPropName = propName.replace(this.selectedWidget.type + '-', '')  //去掉组件名称前缀-，如果有的话！！
      return this.designer.hasConfig(this.selectedWidget, originalPropName)
    },

    getPropEditor(propName, editorName) {
      let originalPropName = propName.replace(this.selectedWidget.type + '-', '')  //去掉组件名称前缀-，如果有的话！！
      let ownPropEditorName = `${this.selectedWidget.type}-${originalPropName}-editor`
      //console.log(ownPropEditorName, this.$options.components[ownPropEditorName])
      if (!!this.$options.components[ownPropEditorName]) {  //局部注册的属性编辑器组件
        return ownPropEditorName
      }

      //return !!this.$root.$options.components[ownPropEditorName] ? ownPropEditorName : editorName  //Vue2全局注册的属性编辑器组件
      return !!this.$root.$.appContext.components[ownPropEditorName] ? ownPropEditorName : editorName  //Vue3全局注册的属性编辑器组件
    },

    showCollapse(propsObj) {
      let result = false

      for (let propName in propsObj) {
        if (!propsObj.hasOwnProperty(propName)) {
          continue
        }

        if (this.hasPropEditor(propName, propsObj[propName])) {
          result = true
          break
        }
      }

      return result
    },

    editEventHandler(eventName, eventParams) {
      this.curEventName = eventName
      this.eventHeader = `${this.optionModel.name}.${eventName}(${eventParams.join(', ')}) {`
      this.eventHandlerCode = this.selectedWidget.options[eventName] || ''
      // 设置字段校验函数示例代码
      if ((eventName === 'onValidate') && (!this.optionModel['onValidate'])) {
        // this.eventHandlerCode = "  /* sample code */\n  /*\n  if ((value > 100) || (value < 0)) {\n    callback(new Error('error message'))  //fail\n  } else {\n    callback();  //pass\n  }\n  */"
      }

      this.eventDialogStore.visible = true
    },

    saveEventHandler() {
      const codeHints = this.$refs.ecEditor.getAnnotations()
      let syntaxErrorFlag = false
      if (!!codeHints && (codeHints.length > 0)) {
        codeHints.forEach((chItem) => {
          if (chItem.type === 'error') {
            syntaxErrorFlag = true
          }
        })

        if (syntaxErrorFlag) {
          VfMessage.error(this.i18nt('designer.setting.syntaxCheckWarning'))
          return
        }
      }
      
      this.selectedWidget.options[this.curEventName] = this.eventHandlerCode.trim()
      this.eventDialogStore.visible = false
    },

    // ----- TODO 新增方法
    /** 清除设置面板的校验 */
    clearSettingValidate() {
      if (this.$refs.fieldSettingFormRef) {
        this.$refs.fieldSettingFormRef.clearValidate()
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.setting-panel {
  height: 100%;
  width: 300px;
  .container-setting-panel {
    padding: 0 8px;
    position: relative;
    .no-widget-hint {
      display: flex;
      text-align: center;
      align-items: center;
      margin-top: 50%;
      justify-content: center;
      font-size: 16px;
      color: #999999;
    }
  }
}

.setting-panel-tabs {
  width: 100%;
  height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column-reverse;
  :deep(.el-tabs__header) {
    margin-bottom: 0;
    .el-tabs__item {
      padding-right: 0;
    }
  }
  :deep(.el-tabs__content) {
    flex: 1;
    overflow: auto;
  }
  .panel-tabs-header {
    padding: 0 20px;
    .header-icon {
      margin-left: 0;
    }
  }
}

.setting-scrollbar {
  :deep(.el-scrollbar__wrap) {
    overflow-x: hidden; /* IE浏览器隐藏水平滚动条箭头！！ */
  }
}

.setting-collapse {
  :deep(.el-collapse-item__content) {
    padding-bottom: 6px;
  }

  :deep(.el-collapse-item__header) {
    font-style: italic;
    font-weight: bold;
  }
}

.setting-form {
  :deep(.el-form-item__label) {
    font-size: 13px;
    //text-overflow: ellipsis;
    overflow: hidden;
    white-space: nowrap;
  }

  :deep(.el-form-item--small.el-form-item) {
    margin-bottom: 8px;
  }
  :deep(.el-form-item__error) {
    position: unset;
  }
}

/* 隐藏Chrome浏览器中el-input数字输入框右侧的上下调整小箭头 */
:deep(.hide-spin-button) input::-webkit-outer-spin-button,
:deep(.hide-spin-button) input::-webkit-inner-spin-button {
  -webkit-appearance: none !important;
}

/* 隐藏Firefox浏览器中el-input数字输入框右侧的上下调整小箭头 */
:deep(.hide-spin-button) input[type="number"] {
  appearance: textfield;
  -moz-appearance: textfield;
}

:deep(.custom-divider.el-divider--horizontal) {
  margin: 10px 0;
}

:deep(.custom-divider-margin-top.el-divider--horizontal) {
  margin: 20px 0;
}
</style>
<style lang="scss">
@import './styles/widget-setting-global.scss'
</style>

